package net.zoneland.knowledge.utils;

import java.io.File;
import java.io.IOException;
import net.zoneland.knowledge.config.EsConfigInterface;

import org.apache.http.Header;
import org.apache.http.HttpHost;
import org.apache.http.message.BasicHeader;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestClientBuilder;
import org.elasticsearch.client.RestHighLevelClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * ElasticSearch 连接池工具类.
 *
 * @author bcc
 */
public final class ElasticSearchPoolUtil {

    /**
     * logger.
     */
    private static final Logger LOGGER = LoggerFactory.getLogger(ElasticSearchPoolUtil.class);

    /**
     * ES配置.
     */
    private static EsConfigInterface esConfig;

    private static RestClientBuilder restClientBuilder;


    private ElasticSearchPoolUtil() {

    }

    /**
     * 获得对象.
     *
     * @return
     * @throws Exception Exception
     */
    public static RestHighLevelClient getClient() throws Exception {
        // 从池中取一个对象
        String[] hosts = esConfig.getServerHost().split(",");
        int length = hosts.length;
        HttpHost[] httpHosts = new HttpHost[length];
        for (int i = 0; i < length; i++) {
            String[] ipAndPort = hosts[i].split(":");
            httpHosts[i] = new HttpHost(ipAndPort[0], Integer.valueOf(ipAndPort[1]), esConfig.getSchema());
        }
        RestHighLevelClient client =   new RestHighLevelClient(restClientBuilder);
        return client;
    }


    public static void initRestClientBuilder() {
        // 从池中取一个对象
        String[] hosts = esConfig.getServerHost().split(",");
        int length = hosts.length;
        HttpHost[] httpHosts = new HttpHost[length];
        for (int i = 0; i < length; i++) {
            String[] ipAndPort = hosts[i].split(":");
            httpHosts[i] = new HttpHost(ipAndPort[0], Integer.valueOf(ipAndPort[1]), esConfig.getSchema());
        }
        try {
            restClientBuilder = getRestClientBuilder(httpHosts);
        } catch (Exception e) {
            LOGGER.error("initRestClientBuilder error", e);
        }
    }
    /**
     * 归还对象.
     *
     * @param client client
     */
    public static void returnClient(RestHighLevelClient client) {
        if (null != client) {
            // 使用完毕之后，归还对象
            try {
                client.close();
            } catch (IOException e) {
                LOGGER.error("RestHighLevelClient close error", e);
            }
        }
    }


    /**
     * Get one rest client builder instance
     */
    private static RestClientBuilder getRestClientBuilder(HttpHost[] hostArray) throws Exception {
        RestClientBuilder builder = null;
        if ("true".equals(esConfig.getIsSecureMode())) {
            setSecConfig();
        } else {
            System.setProperty("es.security.indication", "false");
        }
        builder = RestClient.builder(hostArray);
        Header[] defaultHeaders = new Header[] {new BasicHeader("Accept", "application/json"),
                new BasicHeader("Content-type", "application/json")};

        builder = builder.setRequestConfigCallback(requestConfigBuilder -> requestConfigBuilder.setConnectTimeout(esConfig.getConnectTimeout())
                .setSocketTimeout(esConfig.getSocketTimeout())
                .setConnectionRequestTimeout(esConfig.getConnectionRequestTimeout())).setMaxRetryTimeoutMillis(esConfig.getMaxRetryTimeoutMillis())
                .setMaxConnPerRoute(esConfig.getMaxConnPerRoute()).setMaxConnTotal(esConfig.getMaxConnTotal());

        builder.setDefaultHeaders(defaultHeaders);

        return builder;
    }

    /**
     * Set configurations about authentication.
     */
    private static void setSecConfig() {

        try {
            //获取类加载的根路径
            String path = ElasticSearchPoolUtil.class.getResource("/").getPath();
            // windows path 以斜杠开头，如/D:/workspace/ide，特殊处理，去掉第一个斜杠
            path = new File(path).getAbsolutePath() + File.separator;
            LOGGER.info("Path is  " + path);
            EsLoginUtil.setJaasFile(esConfig.getPrincipal(), path + "user.keytab");
            EsLoginUtil.setKrb5Config(path + "krb5.conf");
            System.setProperty("elasticsearch.kerberos.jaas.appname", "EsClient");
            System.setProperty("es.security.indication", "true");
            LOGGER.info("es.security.indication is  " + System.getProperty("es.security.indication"));
        } catch (Exception e) {
            LOGGER.error("Failed to set security conf", e);
        }
    }

    /**
     * .
     *
     * @return esConfig
     */
    public static EsConfigInterface getEsConfig() {
        return esConfig;
    }

    /**
     * .
     *
     * @param esConfig to set
     */
    public static void setEsConfig(final EsConfigInterface esConfig) {
        ElasticSearchPoolUtil.esConfig = esConfig;
    }
}
